// PGLScript.cpp: implementation of the CPGLScript class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <pgl/mfc/PGLScript.h>
#include <pgl/mfc/PGLMFCGlobal.h>
#include <pgl/mfc/PGLDialog.h>
#include <pgl/mfc/PGLDialogList.h>
#include  <io.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPGLScriptPool::CPGLScriptPool()
{
	PGL_TRACE(_T("CPGLScriptPool constructor"));
};

CPGLScriptPool::~CPGLScriptPool()
{	
	Clear();
	PGL_TRACE(_T("CPGLScriptPool Destructor"));
};

void CPGLScriptPool::Clear()
{
	m_scripts.clear();
};

void CPGLScriptPool::CreateScript(CString& str)
{
	str.Format(_T("pgl_script_%d"),m_scripts.size()+1000);

	m_scripts[str]=CPGLScriptPtr(new CPGLScript);
}
	
CPGLScriptPtr CPGLScriptPool::GetScript(LPCTSTR szScriptName)
{
	ScriptMap::iterator it=m_scripts.find( szScriptName );
	if (it != m_scripts.end())
		return it->second;
	else
		return CPGLScriptPtr();
}

void CPGLScriptPool::RemoveScript( LPCTSTR szScriptName )
{
	if ( m_scripts.find( szScriptName )!= m_scripts.end() )
		m_scripts.erase(szScriptName);
}

CPGLScript::CPGLScript()
: 
m_dwCurDlgID(0), 
m_dwCurRegionID(0),
m_bAutoZoom(true),
m_lDialogs(new CPGLDialogList)
{
	PGL_TRACE(_T("CPGLScript constructor\n"));
}

CPGLScript::~CPGLScript()
{
	CloseAllFigures();
	CloseAllRegions();
}


long CPGLScript::Figure()
{
	CPGLRegionPtr pRegion(new CPGLRegion());
	if (!pRegion)
		return 0;

	m_dwCurRegionID=pRegion->GetID();

	CPGLDialog* pDlg= new CPGLDialog( NULL, pRegion);
	if (!pDlg)
		return 0;

	ASSERT(m_lDialogs);
	m_lDialogs->AddHead(pDlg);

	return m_dwCurDlgID=pDlg->GetID();
}

long CPGLScript::Region()
{
	CPGLRegionPtr pRegion(new CPGLRegion());
	if (!pRegion)
		return 0;

	// adding to container...
	m_pRegions[pRegion->GetID()]=pRegion;

	return m_dwCurRegionID=pRegion->GetID();
}

bool CPGLScript::SetCR( long dwRegionID)
{
	CPGLRegionStPtr pRegion(GetRegion(dwRegionID));
	if (pRegion)
	{
		ASSERT(m_lDialogs);
		CPGLDialog* pDlg=m_lDialogs->FindFromRegion(dwRegionID);
		if (pDlg)
			m_dwCurDlgID=pDlg->GetID();
		else
			m_dwCurDlgID=0;

		m_dwCurRegionID=dwRegionID;
		return true;
	}
	else
		return false;
}

CPGLRegionStPtr CPGLScript::GetRegion( long lRegionID)
{
	CPGLRegionStPtr pRegion;

	// try getting object from given ID
	pRegion=CPGLRegionPoolSingleton::Find( lRegionID );

	// if didn't work, try getting from current region ID
	if (!pRegion)
		pRegion=CPGLRegionPoolSingleton::Find(m_dwCurRegionID );

	return pRegion;
}

CPGLRegionPtr CPGLScript::GetRegionPtr( long lRegionID)
{
	RegionPtrContainer::iterator it;

	it=m_pRegions.find(lRegionID);
	if (it != m_pRegions.end())
		return it->second;
	else 
		return CPGLRegionPtr();
}

CPGLDialog* CPGLScript::GetCurrentDialog()
{
	ASSERT(m_lDialogs);
	return m_lDialogs->Find( m_dwCurDlgID );
}


CPGLRegionStPtr CPGLScript::GetSafeRegion(long lRegionID)
{
	CPGLRegionStPtr pRegion( GetRegion(lRegionID) );

	if (pRegion)
		return pRegion;

	Figure();
	pRegion = CPGLRegionPoolSingleton::Find( m_dwCurRegionID );

	return pRegion;
}


int CPGLScript::DoModalRegion( long lRegionID , DWORD dwFlags)
{	
	CPGLRegionPtr pRegion = GetRegionPtr(lRegionID);
	if(!pRegion)
		return IDCANCEL;


	HINSTANCE hInst=AfxGetResourceHandle();
	AfxSetResourceHandle(CPGLMFCGlobal::GetInstance());
	CPGLDialog dlg( CWnd::GetDesktopWindow(), pRegion, dwFlags);

	int result=dlg.DoModal();
	AfxSetResourceHandle(hInst);

	return result;
}

long CPGLScript::Plot(long lRegionID, CPGLDataPtr pX, CPGLDataPtr pY, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));
	if (!pRegion)
		return 0;

	if (!pX || !pY || !pX->size() || !pY->size() )
		return 0;

	// creating line...
	CPGLLine2DPtr pLine(new CPGLLine2D);
	if (!pLine)
		return 0;

	pLine->SetDatas( pX, pY);

	// setting flags...
	ParseLineFormat( pLine, szFlags );

	pRegion->AddObject(pLine);

	Update(pRegion, true);
	
	return pLine->GetID();
}


long CPGLScript::PlotHor(long lRegionID, float fY, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion( GetSafeRegion(lRegionID) );
	if (!pRegion)
		return 0;

	CPGLLineHorPtr pHor(new CPGLLineHor);
	if (!pHor)
		return 0;

	pHor->SetY(fY);
	ParseLineFormat( pHor, szFlags );

	pRegion->AddObject( pHor);
	Update(pRegion,true);

	return pHor->GetID();
}

long CPGLScript::PlotVer(long lRegionID, float fX, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));
	if (!pRegion)
		return 0;

	CPGLLineVerPtr pVer(new CPGLLineVer);
	if (!pVer)
		return 0;

	pVer->SetX(fX);
	ParseLineFormat( pVer, szFlags );

	pRegion->AddObject( pVer);
	Update(pRegion,true);

	return pVer->GetID();
}

long CPGLScript::PlotFcn(long lRegionID, CPGLDataPtr pX, LPCTSTR szFcnX, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));
	if (!pRegion)
		return 0;

	if (!pX || !pX->size())
		return 0;

	// creating line...
	CPGLLine2DPtr pLine(new CPGLLine2D);
	if (!pLine)
		return 0;

	CPGLMathFcnDataPtr pY(new CPGLMathFcnData( pX->Clone() ));
	pY->Parse((_tcslen(szFcnX)) ? szFcnX : _T("x"), _T("x"));
	pLine->SetDatas( pX, pY);

	// setting flags...
	ParseLineFormat( pLine, szFlags );

	pRegion->AddObject(pLine);

	Update(pRegion, true);
	
	return pLine->GetID();
}

long CPGLScript::PlotFcnY(long lRegionID, long nSteps, float fX0, float fXStep, LPCTSTR szFcnX, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));

	if (!pRegion)
		return 0;

	if (!nSteps)
		return 0;

	// creating line...
	CPGLLine2DPtr pLine(new CPGLLine2D);
	if (!pLine)
		return 0;

	CPGLLinearVectorPtr pX(new CPGLLinearVector( fX0, fXStep, nSteps ));
	if (!pX)
		return 0;

	CPGLMathFcnDataPtr pY(new CPGLMathFcnData( pX->Clone() ));
	if (!pY)
		return 0;

	pY->Parse((_tcslen(szFcnX)) ? szFcnX : _T("x"), _T("x"));
	pLine->SetDatas( pX, pY);

	// setting flags...
	ParseLineFormat( pLine, szFlags );

	pRegion->AddObject(pLine);

	Update(pRegion, true);
	
	return pLine->GetID();
}


long CPGLScript::PlotY(long lRegionID, float fX0, float fXStep, CPGLDataPtr pY, LPCTSTR szFlags)
{
	if (!pY || !fXStep)
		return 0;

	CPGLLinearVectorPtr pX(new CPGLLinearVector(fX0, fXStep, pY->size()) );
	
	return Plot( lRegionID, pX, pY, szFlags);
}

long CPGLScript::PlotLODY(long lRegionID, float fX0, float fXStep, CPGLDataPtr pY, float fCompRatio, LPCTSTR szFlags)
{
	if (!pY || !fXStep)
		return 0;

	CPGLLinearVectorPtr pX( new CPGLLinearVector(fX0, fXStep, pY->size()) );
	
	return PlotLOD( lRegionID, pX, pY, fCompRatio, szFlags);
}

long CPGLScript::Scatter(long lRegionID, CPGLDataPtr pX, CPGLDataPtr pY, CPGLDataPtr pValues, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));
	if (!pRegion)
		return 0;

	if (!pX || !pY || !pValues || !pX->size() || !pY->size() || !pValues->size())
		return 0;

	// creating line...
	CPGLScatterPtr pScatter(new CPGLScatter);
	if (!pScatter)
		return 0;

	pScatter->SetDatas(pX, pY, pValues);

	// setting flags...
	ParseScatterFormat( pScatter, szFlags );

	pRegion->AddObject(pScatter);

	Update(pRegion, true);
	
	return pScatter->GetID();
}

long CPGLScript::PlotLOD(long lRegionID, CPGLDataPtr pX, CPGLDataPtr pY,  float fCompressionRatio, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));
	if (!pRegion)
		return 0;

	if (!pX || !pY || !pX->size() || !pY->size() )
		return 0;

	// creating line...
	CPGLLine2DLODPtr pLine(new CPGLLine2DLOD);
	if (!pLine)
		return 0;

	pLine->SetDatas( pX, pY);
	pLine->ShrinkNorm(fCompressionRatio);

	// setting flags...
	ParseLineFormat( pLine, szFlags );

	pRegion->AddObject(pLine);
	
	Update(pRegion, true);
	
	return pLine->GetID();
}

long CPGLScript::CandleStick(long lRegionID, float fX0, float fXStep, CPGLDataPtr pOpen, CPGLDataPtr pHigh, CPGLDataPtr pLow, CPGLDataPtr pClose, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));
	
	if (!pRegion)
		return 0;
	
	if (!pOpen || !pHigh || !pLow || !pClose || !fXStep)
		return 0;
	
	CPGLStockPtr pStock(new CPGLStock);
	if (!pStock)
		return 0;
	
	pStock->SetX0(fX0);
	pStock->SetDx(fXStep);
	pStock->SetDatas( pOpen, pHigh, pLow, pClose);
	pStock->SetType( CPGLStock::TypeCandleStick);
	
	// setting flags...
	ParseLineFormat( pStock, szFlags );
	
	pRegion->AddObject(pStock);
	
	Update(pRegion, true);
	
	return pStock->GetID();
};

long CPGLScript::Stock(long lRegionID, float fX0, float fXStep, CPGLDataPtr pOpen, CPGLDataPtr pHigh, CPGLDataPtr pLow, CPGLDataPtr pClose, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));

	if (!pRegion)
		return 0;

	if (!pOpen || !pHigh || !pLow || !pClose || !fXStep)
		return 0;

	CPGLStockPtr pStock(new CPGLStock);
	if (!pStock)
		return 0;

	pStock->SetX0(fX0);
	pStock->SetDx(fXStep);
	pStock->SetDatas( pOpen, pHigh, pLow, pClose);
	pStock->SetType( CPGLStock::TypeOpenHighLowClose);	

	// setting flags...
	ParseLineFormat( pStock, szFlags );

	pRegion->AddObject(pStock);

	Update(pRegion, true);
	
	return pStock->GetID();
};

long CPGLScript::ErrorBar(long lRegionID, CPGLDataPtr pX, CPGLDataPtr pY, CPGLDataPtr pErrorUp, CPGLDataPtr pErrorDown, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));

	if (!pRegion)
		return 0;

	if (!pX || !pY || !pErrorUp || !pErrorDown || !pErrorUp->size() || !pErrorDown->size())
		return 0;

	CPGLErrorBarPtr pErrorBar(new CPGLErrorBar);
	if (!pErrorBar)
		return 0;

	pErrorBar->SetDatas( pX, pY);
	pErrorBar->SetErrorDatas( pErrorUp, pErrorDown);
	

	// setting flags...
	ParseErrorBarFormat( pErrorBar, szFlags );

	pRegion->AddObject(pErrorBar);

	Update(pRegion, true);
	
	return pErrorBar->GetID();
};

long CPGLScript::ErrorBarY(
    long lRegionID, 
    float fX0, 
    float fXStep, 
    CPGLDataPtr pY, 
    CPGLDataPtr pErrorUp, 
    CPGLDataPtr pErrorDown, 
    LPCTSTR szFlags
    )
{
	if (!pY || !fXStep)
		return 0;
	
	CPGLLinearVectorPtr pX(new CPGLLinearVector(fX0, fXStep, pY->size()) );
	
	return ErrorBar( lRegionID, pX, pY, pErrorUp, pErrorDown, szFlags );
}


long CPGLScript::Histogram(
     long lRegionID, 
     CPGLDataPtr pY, 
     LPCTSTR szFlags
     )
{
	CPGLRegionStPtr pRegion(GetSafeRegion(lRegionID));

	if (!pRegion)
		return 0;

	if (!pY || !pY->size())
		return 0;	

	// creating line...
	CPGLHistogramPtr pHist(new CPGLHistogram);
	if (!pHist)
		return 0;

	pHist->SetValues(pY);

	// setting flags...
	ParseLineFormat( pHist, szFlags );

	pRegion->AddObject(pHist);

	Update(pRegion, true);
	
	return pHist->GetID();
};

long CPGLScript::FixedStepMap(long lRegionID, long nXSteps, float fX0, float fXStep, long nYSteps, float fY0, float fYStep, CPGLDataPtr pValues, LPCTSTR szFlags)
{
/*	CPGLRegionPtr pRegion(GetSafeRegion(lRegionID));
	CPGLContourMap* pMap=NULL;

	if (!pRegion)
		goto Cleaning;

	if (!pValues || pValues->size() < nXSteps* nYSteps)
		goto Cleaning;	

	// creating line...
	pMap = new CPGLMapZ;
	if (!pMap)
		goto Cleaning;

	pMap->SetField( new contour::TFieldMap<float>( pValues

	pMap->SetValues(pY);

	// setting flags...
	ParseLineFormat( pHist, szFlags );

	pRegion->AddObject(pHist);

	Update(pRegion, true);
	
	return pHist->GetID();

Cleaning:
*/
	return 0;
}

long CPGLScript::RegularMap(
    long lRegionID, 
    CPGLDataPtr pX, 
    CPGLDataPtr pY, 
    CPGLDataPtr pValues, 
    LPCTSTR szFlags)
{
	return 0;
}

long CPGLScript::FixedStepVectorField(long lRegionID, long nXSteps, float fX0, float fXStep, long nYSteps, float fY0, float fYStep, CPGLDataPtr pVx, CPGLDataPtr pVy, LPCTSTR szFlags)
{
	return 0;
}

long CPGLScript::RegularVectorField(long lRegionID, CPGLDataPtr pX, CPGLDataPtr pY, CPGLDataPtr pVx, CPGLDataPtr pVy, LPCTSTR szFlags)
{
	return 0;
}

void CPGLScript::Update(CPGLRegionStPtr pRegion, bool bZoomAll)
{
	if (!pRegion)
		return;

	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if(pDlg)
	{
		if (m_bAutoZoom && bZoomAll)
			pRegion->ZoomAll( pDlg->GetGfxInterface() );
		pDlg->SetDirty();
	}
	else
	{
		if (m_bAutoZoom && bZoomAll)
			pRegion->ZoomAll( m_gdip );
	}
}

void CPGLScript::CloseFigure( long dwID)
{
	if (dwID == 0)
	{
		CPGLRegionStPtr pRegion = GetRegion(dwID);
		if (pRegion)
			dwID = pRegion->GetID();
	}

	ASSERT(m_lDialogs);
	m_lDialogs->Remove(m_lDialogs->FindFromRegion(dwID));
};

void CPGLScript::CloseRegion( long dwID )
{
	CPGLRegionStPtr pRegion=GetRegion(dwID);
	if (!pRegion)
		return;

	if (dwID == m_dwCurRegionID)
		m_dwCurRegionID=0;

	m_pRegions.erase( m_pRegions.find( dwID ));
}

void CPGLScript::CloseAllFigures()
{
	ASSERT(m_lDialogs);
	m_lDialogs->RemoveAll();
	m_dwCurDlgID=0;
	m_dwCurRegionID=0;
}

void CPGLScript::CloseAllRegions()
{
	m_pRegions.clear();
	m_dwCurDlgID=0;
	m_dwCurRegionID=0;
}

long CPGLScript::Layout(long lRegionID, LPCTSTR szLayout)
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return 0;
	
	pRegion->Layout( szLayout );
	
	Update(pRegion,false);
	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if (pDlg)
		pDlg->PostResize();
	
	return pRegion->GetID();
}

long CPGLScript::Divide( long lRegionID, size_t nRows, size_t nCols)
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return 0;

	if ( pRegion->GetNChildren() != nRows* nCols)
		pRegion->Divide( nRows, nCols );

	Update(pRegion,false);
	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if (pDlg)
		pDlg->PostResize();

	return pRegion->GetID();
}

long CPGLScript::GetParent( long uID )
{
	CPGLObjectStPtr pObject = CPGLObjectPoolSingleton::Find( uID );
	if (!pObject)
		return 0;

	CPGLRegionStPtr pParent = pObject->GetParent();
	if (pParent)
		return pParent->GetID();
	else
		return 0;
}


void CPGLScript::GetHelp(long uID, CString& str )
{
	CPGLObjectStPtr pObject = CPGLObjectPoolSingleton::Find( uID );
	if (!pObject)
	{
		str="Could not find object with ID %d";
		return;
	}

	pObject->Help(str);
}

long CPGLScript::GetChild( long lRegionID, size_t uIndex )
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	// gettin child
	CPGLRegionPtr pChild=pRegion->GetChild( uIndex );
	if( pChild)
		return pChild->GetID();
	else
		return 0;
}

long CPGLScript::GetChildrenSize( long lRegionID )
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	return (long)pRegion->GetNChildren();
}

long CPGLScript::OutOfChild()
{
	CPGLRegionStPtr pRegion = GetRegion( m_dwCurRegionID );
	if (pRegion && pRegion->GetParent())
		pRegion = pRegion->GetParent();

	if (pRegion)
		return pRegion->GetID();
	else
		return 0;
}

long CPGLScript::Title(long lRegionID, LPCTSTR szTitle )
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	CPGLText& pText = pRegion->GetAxe()->GetLabel( CPGLAxe2D::ELabelTop );

	pText.SetString(szTitle);
	pText.Show();
	
	Update(pRegion,false);

	return pText.GetID();
}

long CPGLScript::LeftLabel(long lRegionID, LPCTSTR szLabel)
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	CPGLText& pText = pRegion->GetAxe()->GetLabel( CPGLAxe2D::ELabelLeft);

	pText.SetString(szLabel);
	pText.Show();
	
	Update(pRegion,false);

	return pText.GetID();
}
	
long CPGLScript::BottomLabel(long lRegionID, LPCTSTR szLabel)
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	CPGLText& pText = pRegion->GetAxe()->GetLabel( CPGLAxe2D::ELabelBottom);

	pText.SetString(szLabel);
	pText.Show();
	
	Update(pRegion,false);

	return pText.GetID();
}

long CPGLScript::RightLabel(long lRegionID, LPCTSTR szLabel)
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	CPGLText& pText = pRegion->GetAxe()->GetLabel( CPGLAxe2D::ELabelRight);

	pText.SetString(szLabel);
	pText.Show();
	
	Update(pRegion,false);

	return pText.GetID();
}

long CPGLScript::Grid(long lRegionID, LPCTSTR szState)
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	long dwID=0;
	if (!pRegion)
		return 0;

	CPGLAxe2D* pAxe=pRegion->GetAxe();
	CString s(szState);

	if (s=="on")
	{
		pAxe->ShowHorGrid( true );
		pAxe->ShowVerGrid( true );
	}
	else if (s=="off")
	{
		pAxe->ShowHorGrid( false );
		pAxe->ShowVerGrid( false );
	}
	else if (s=="xon")
	{
		pAxe->ShowHorGrid( true );
		dwID = pAxe->GetHorGrid().GetID();
	}
	else if (s=="xoff")
	{
		pAxe->ShowHorGrid( false );
		dwID = pAxe->GetHorGrid().GetID();
	}
	else if (s=="yon")
	{
		pAxe->ShowVerGrid( true );
		dwID = pAxe->GetVerGrid().GetID();
	}
	else if (s=="yoff")
	{
		pAxe->ShowVerGrid( false );
		dwID = pAxe->GetVerGrid().GetID();
	}

	Update(pRegion,false);

	return dwID;
}

void CPGLScript::AutoZoom(LPCTSTR szState)
{
	CString s(szState);
	s.MakeLower();
	s.TrimLeft();
	s.TrimRight();
	
	m_bAutoZoom= ( s == "on" || s=="true");
}

long CPGLScript::Legend(long lRegionID)
{
	CPGLRegionStPtr pRegion=GetRegion(lRegionID);
	if (!pRegion)
		return 0;
		
	CPGLLegendPtr pLegend=pRegion->AddLegend();	
	if (!pLegend)
		return 0;
		
	Update(pRegion,false);
	return pLegend->GetID();
}

void CPGLScript::ParseObjectFormat(CPGLObjectPtr pObject, LPCTSTR szFormat)
{
	if (!pObject)
		return;

	size_t index=0;
	while (index < _tcslen( szFormat))
	{
		switch( szFormat[index++])
		{
		case 'y':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::Yellow) );
			break;
		case 'm':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::Magenta) );
			break;
		case 'c':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::Cyan) );
			break;
		case 'r':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::Red) );
			break;
		case 'g':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::Green) );
			break;
		case 'b':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::Blue) );
			break;
		case 'w':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::White) );
			break;
		case 'k':
			pObject->SetColor( CPGLColor::GetClassicColor(CPGLColor::Black) );
			break;
		}
	}
}

void CPGLScript::ParseLineFormat(CPGLLinePtr pLine, LPCTSTR szFormat)
{
	if (!pLine)
		return;

	ParseObjectFormat( pLine, szFormat);

	size_t index=0;
	while (index < _tcslen( szFormat))
	{
		switch( szFormat[index++])
		{
		// line dashing...
		case '-':
			if ( index < _tcslen(szFormat))
			{
				switch( szFormat[index++])
				{
				case '-':
					pLine->SetDashPattern(PGL_LINE_BARBAR);
					break;
				case '.':
					pLine->SetDashPattern(PGL_LINE_BARPOINT);
					break;
				}
			}
			break;
		case ':':
			pLine->SetDashPattern(PGL_LINE_POINTPOINT);
			break;
		// markers
		case '.':
			pLine->SetMarkerType( CPGLLine::MarkerTypeCircle);
			break;
		case 'o':
			pLine->SetMarkerType( CPGLLine::MarkerTypeContour);
			break;
		case 's':
			pLine->SetMarkerType( CPGLLine::MarkerTypeSquare);
			break;
		case '^':
			pLine->SetMarkerType( CPGLLine::MarkerTypeTriangle);
			break;
		case 'q':
			if ( index < _tcslen(szFormat)+1)
			{
				CPGLCharMarkerPtr pMarker(new CPGLCharMarker( pLine->GetColor() ));
				pMarker->SetString(szFormat[index++]);
				pLine->SetMarker( pMarker );
			}
			break;
		}
	}
}


void CPGLScript::ParseImageFormat(CPGLImagePtr pImage, LPCTSTR szFormat)
{
	if (!pImage)
		return;
	ParseObjectFormat(pImage, szFormat);
	/*
	int index=0;
	while (index < _tcslen( szFormat))
	{
		switch( szFormat[index++])
		{
		}
	}
	*/
}


void CPGLScript::ParseScatterFormat(CPGLScatterPtr pScatter, LPCTSTR szFormat)
{
	if (!pScatter)
		return;

	ParseObjectFormat(pScatter, szFormat);


	CString str;
	size_t index=0;
	while (index < _tcslen( szFormat))
	{
		switch( szFormat[index++])
		{
		// markers
		case '.':
			pScatter->SetMarkerType( CPGLScatter::MarkerTypeCircle);
			break;
		case 's':
			pScatter->SetMarkerType( CPGLScatter::MarkerTypeSquare);
			break;
		case '^':
			pScatter->SetMarkerType( CPGLScatter::MarkerTypeTriangle);
			break;
		case 'q':
			if ( index < _tcslen(szFormat)+1)
			{
				pScatter->SetMarkerType( CPGLScatter::MarkerTypeText );
				str=szFormat[++index];
				pScatter->SetString( str );
			}
			break;
		case 'h':
			pScatter->SetColorMap( CPGLUtility::ColorMapHsv );
			break;
		case 'j':
			pScatter->SetColorMap( CPGLUtility::ColorMapJet );
			break;
		case 'o':
			pScatter->SetColorMap( CPGLUtility::ColorMapHot );
			break;
		case 'e':
			pScatter->SetColorMap( CPGLUtility::ColorMapGray );
			break;
		case 'a':
			pScatter->SetColorMap( CPGLUtility::ColorMapAutumn );
			break;
		case 'u':
			pScatter->SetColorMap( CPGLUtility::ColorMapSummer );
			break;
		case 'z':
			pScatter->SetColorMap( CPGLUtility::ColorMapWinter );
			break;
		case 'p':
			pScatter->SetColorMap( CPGLUtility::ColorMapPink );
			break;
		case 'l':
			pScatter->SetColorMap( CPGLUtility::ColorMapCool );
			break;
		case 'n':
			pScatter->SetColorMap( CPGLUtility::ColorMapBone );
			break;
		case 'd':
			pScatter->SetColorMap( CPGLUtility::ColorMapCopper );
			break;
		}
	}
}

void CPGLScript::ParseErrorBarFormat(CPGLErrorBarPtr pError, LPCTSTR szFormat)
{
	if (!pError)
		return;

	ParseLineFormat( pError, szFormat);
	size_t index=0;
	while (index < _tcslen( szFormat))
	{
		switch( szFormat[index++])
		{
			// horizontal
		case 'h':
			pError->SetVertical(false);
			break;
			// vertical
		case 'v':
			pError->SetVertical(true);
			break;
			// absolute
		case 'p':
			pError->SetAbsolute(true);
			break;
			// relative
		case 't':
			pError->SetAbsolute(false);
			break;
		};
	};
};

void CPGLScript::Set(long uID, LPCTSTR szPropAndValues)
{
	CPGLObjectStPtr pObject = CPGLObjectPoolSingleton::Find( uID );
	if (!pObject)
		return;

	pObject->Set(szPropAndValues);
	Update(GetRegion(0),false);
}

void CPGLScript::Get( long uID, LPCTSTR szProp, CString& sValue)
{
	CPGLObjectStPtr pObject = CPGLObjectPoolSingleton::Find( uID );
	if (!pObject)
		return;

	pObject->Get(szProp, sValue);
}

bool CPGLScript::LoadCSVFile( long lRegionID, LPCTSTR szFileName)
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return false;

	// load file...
	bool bSuccess=pRegion->LoadCSVFile(szFileName);
	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if (pDlg)
		pDlg->SetDirty();

	return bSuccess;
}


long CPGLScript::LoadFromXML( long lRegionID, LPCTSTR szFileName )
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return 0;

	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if (pDlg)
	{
		CPGLArchive ar(pRegion, &pDlg->GetGfxInterface());
		ar.Load( szFileName );
		Update(pRegion,false);
	}
	else
	{
		CPGLArchive ar(pRegion);
		ar.Load( szFileName );
	}

	return pRegion->GetID();
};

bool CPGLScript::SaveToXML( long lRegionID, LPCTSTR szFileName, bool bZipping )
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return false;

	bool bSuccess;
	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if (pDlg)
	{
		CPGLArchive ar(pRegion, &pDlg->GetGfxInterface());
		ar.SetZipping(bZipping);
		bSuccess=ar.Save( szFileName );
		Update(pRegion,false);
	}
	else
	{
		CPGLArchive ar(pRegion);
		ar.SetZipping(bZipping);
		bSuccess=ar.Save( szFileName );
		pRegion->RefreshView( m_gdip, true);
	}

	return bSuccess;
};


/*
		- jpeg followed by quality level from 1 (poor) to 100 (good)
		- bmp, Windows bitmap
		- png, PNG
		- tiff, TIFF
		- emf, Extented Metafile compatible with GDI only
		- emfp, Extented Metafile compatible with GDI+ only
		- emfpd,  Extented Metafile compatible with GDI and GDI+
		- eps, Encapsulated Postscript
		- svg, Scalable Vector Graphic
		- svgz, Zipped Scalable Vector Graphic
*/
bool CPGLScript::RenderToFile( 
    long lRegionID, 
    LPCTSTR szFileName, 
    LPCTSTR szFormat 
)
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return false;

	CPGLArchive::EFileFormat ff;
	CPGLPointU dim(640,480);
	CString s;
	long quality(75);
    DWORD renderOption(0);
    CString caption;

	parsers::CCmdParser parser;

	////////////////////////////////////////////////
	// Type
	parser.Parse( szFormat );
	if ( parser.HasKey( _T("type"),s ) )
	{
		if (s==_T("jpeg"))
			ff=CPGLArchive::FileFormatJPG;
		if (s==_T("jpg"))
			ff=CPGLArchive::FileFormatJPG;
		else if (s==_T("bmp"))
			ff=CPGLArchive::FileFormatBMP;
		else if (s==_T("tiff"))
			ff=CPGLArchive::FileFormatTIFF;
		else if (s==_T("emfp"))
			ff=CPGLArchive::FileFormatEMFOnly;
		else if (s==_T("emf"))
			ff=CPGLArchive::FileFormatEMFPlusOnly;
		else if (s==_T("emfpd"))
			ff=CPGLArchive::FileFormatEMFPlusDual;
		else if (s==_T("eps"))
			ff=CPGLArchive::FileFormatEPS;
		else if (s==_T("svg"))
			ff=CPGLArchive::FileFormatSVG;
		else if (s==_T("svgz"))
			ff=CPGLArchive::FileFormatSVGZ;
		else 
			ff=CPGLArchive::FileFormatPNG;
	}
	else
		ff=CPGLArchive::FileFormatPNG;

	////////////////////////////////////////////////
	// Quality
	if ( ff == CPGLArchive::FileFormatJPG && parser.HasKey( _T("quality"), s) )
	{
		if (1!=_stscanf( s, _T("%l"), &quality))
			quality=75;
	}

	////////////////////////////////////////////////
	// Dimension
	if ( parser.HasKey( _T("dim"), s) )
	{
		if (2!=_stscanf(s,_T("%dx%d"), &dim.x, &dim.y))
			dim=CPGLPointU(640,480);
	}

    /////////////////////////////////////////////////
    // render options
    if (parser.HasKey(_T("ropt"),s))
    {
        if (s.Find('a'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoAntiAlias;
        if (s.Find('t'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoTextAntiAlias;
        if (s.Find('i'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoBiCubicInterpolation;
    }
    parser.HasKey( _T("caption"), caption);

	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	bool bSuccess;
	if (pDlg)
	{
		CRect rect;
		pDlg->GetClientRect(&rect);
		CPGLArchive ar(pRegion, &pDlg->GetGfxInterface());

        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);		
		if (ff == CPGLArchive::FileFormatJPG)
			ar.SetJPEGQuality( quality );

		bSuccess=ar.ExportToFile( ff,szFileName, dim );
		
		pDlg->PostResize();
		
		Update(pRegion,false);
	}
	else
	{
		CPGLArchive ar(pRegion);

		if (ff == CPGLArchive::FileFormatJPG)
			ar.SetJPEGQuality( quality );

        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);		
		bSuccess=ar.ExportToFile( ff,szFileName, dim );
	}

	return bSuccess;
};

bool CPGLScript::RenderToStream(
    long lRegionID, 
    IStream* pStream, 
    LPCTSTR szFormat
    )
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return false;

	CPGLArchive::EFileFormat ff;
	CPGLPointU dim(640,480);
	CString s;
	long quality(75);
    DWORD renderOption(0);
    CString caption;

	parsers::CCmdParser parser;

	////////////////////////////////////////////////
	// Type
	parser.Parse( szFormat );
	if ( parser.HasKey( _T("type"),s ) )
	{
		if (s==_T("jpeg"))
			ff=CPGLArchive::FileFormatJPG;
		if (s==_T("jpg"))
			ff=CPGLArchive::FileFormatJPG;
		else if (s==_T("bmp"))
			ff=CPGLArchive::FileFormatBMP;
		else if (s==_T("tiff"))
			ff=CPGLArchive::FileFormatTIFF;
		else if (s==_T("emfp"))
			ff=CPGLArchive::FileFormatEMFOnly;
		else if (s==_T("emf"))
			ff=CPGLArchive::FileFormatEMFPlusOnly;
		else if (s==_T("emfpd"))
			ff=CPGLArchive::FileFormatEMFPlusDual;
		else 
			ff=CPGLArchive::FileFormatPNG;
	}
	else
		ff=CPGLArchive::FileFormatPNG;

	////////////////////////////////////////////////
	// Quality
	if ( ff == CPGLArchive::FileFormatJPG && parser.HasKey( _T("quality"), s) )
	{
		if (1!=_stscanf( s, _T("%l"), &quality))
			quality=75;
	}

	////////////////////////////////////////////////
	// Dimension
	if ( parser.HasKey( _T("dim"), s) )
	{
		if (2!=_stscanf(s,_T("%dx%d"), &dim.x, &dim.y))
			dim=CPGLPointU(640,480);
	}

    /////////////////////////////////////////////////
    // render options
    if (parser.HasKey(_T("ropt"),s))
    {
        if (s.Find('a'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoAntiAlias;
        if (s.Find('t'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoTextAntiAlias;
        if (s.Find('i'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoBiCubicInterpolation;
    }
    parser.HasKey( _T("caption"), caption);

	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	bool bSuccess;
	if (pDlg)
	{
		CRect rect;
		pDlg->GetClientRect(&rect);
		CPGLArchive ar(pRegion, &pDlg->GetGfxInterface());

		if (ff == CPGLArchive::FileFormatJPG)
			ar.SetJPEGQuality( quality );

        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);		
		bSuccess=ar.ExportToStream( ff,pStream, dim );
		
		pDlg->PostResize();
		
		Update(pRegion,false);
	}
	else
	{
		CPGLArchive ar(pRegion);

		if (ff == CPGLArchive::FileFormatJPG)
			ar.SetJPEGQuality( quality );

        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);		

        bSuccess=ar.ExportToStream( ff,pStream, dim );
	}

	return bSuccess;
}

void CPGLScript::ZoomAll(long lRegionID, bool bRecurse)
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return;
	
	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if (pDlg)
	{
		pRegion->ZoomAll(pDlg->GetGfxInterface(), bRecurse);
		pDlg->SetDirty();
	}
	else
		pRegion->ZoomAll(m_gdip, bRecurse);
}

void CPGLScript::Zoom(long lRegionID, CPGLRectD rect)
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return;
	
	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	if (pDlg)
	{
		pRegion->ZoomRegion(pDlg->GetGfxInterface(), rect);
		pDlg->SetDirty();
	}
	else
		pRegion->ZoomRegion(m_gdip, rect);
}

bool CPGLScript::GetZoom(long lRegionID, CPGLRectD& rect)
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return false;
	
	rect=pRegion->GetAxe()->GetExtent();
	return true;
}

bool CPGLScript::RenderToImage(
    long lRegionID, 
    Gdiplus::Image* pImage,
    LPCTSTR szFlags
    )
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return false;

	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	bool bSuccess;
    CString s;
    parsers::CCmdParser parser;
    DWORD renderOption(0);
    CString caption;

    ////////////////////////////////////////////////
    // Type
    parser.Parse( szFlags );
    if ( parser.HasKey( _T("ropt"), s) )
    {
        if (s.Find('a'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoAntiAlias;
        if (s.Find('t'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoTextAntiAlias;
        if (s.Find('i'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoBiCubicInterpolation;
    }
    parser.HasKey( _T("caption"), caption);

	if (pDlg)
	{
		CRect rect;
		pDlg->GetClientRect(&rect);
		CPGLArchive ar(pRegion, &pDlg->GetGfxInterface());

        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);

		bSuccess=ar.ExportToImage( pImage );
		
		pDlg->PostResize();
		
		Update(pRegion,false);
	}
	else
	{
		CPGLArchive ar(pRegion);

        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);

		bSuccess=ar.ExportToImage( pImage );
	}

	return bSuccess;
}


bool CPGLScript::RenderToBitmap(
					  long lRegionID,
					  unsigned int width_,
					  unsigned int height_,
					  unsigned int stride_,
					  unsigned int bpp_,
					  void* bits_,
                      LPCTSTR szFlags
                      )
{
	CPGLRegionStPtr pRegion = GetSafeRegion(lRegionID);
	if (!pRegion)
		return false;

	ASSERT(m_lDialogs);
	CPGLDialog* pDlg=m_lDialogs->FindFromRegion(pRegion->GetID());
	bool bSuccess;
    parsers::CCmdParser parser;
    DWORD renderOption(0);
    CString caption;
    CString s;

    ////////////////////////////////////////////////
    // Type
    parser.Parse( szFlags );
    if ( parser.HasKey( _T("ropt"), s) )
    {
        if (s.Find('a'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoAntiAlias;
        if (s.Find('t'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoTextAntiAlias;
        if (s.Find('i'))
            renderOption|=gfxinterface::CGfxInterface::RenderOptionNoBiCubicInterpolation;
    }
    parser.HasKey( _T("caption"), caption);


	if (pDlg)
	{
		CRect rect;
		pDlg->GetClientRect(&rect);
		CPGLArchive ar(pRegion, &pDlg->GetGfxInterface());


        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);
        bSuccess=ar.ExportToBitmap(
			width_,
			height_,
			stride_,
			bpp_,
			reinterpret_cast<BYTE*>(bits_)
			);

		pDlg->PostResize();

		Update(pRegion,false);
	}
	else
	{
		CPGLArchive ar(pRegion);


        ar.SetRenderOption(renderOption);
        if (!caption.IsEmpty())
            ar.SetTextOverlay(caption);
        bSuccess=ar.ExportToBitmap(
			width_,
			height_,
			stride_,
			bpp_,
			reinterpret_cast<BYTE*>(bits_)
			);
	}

	return bSuccess;
};

long CPGLScript::GetObject( long lRegionID, size_t uIndex )
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	CPGLObjectPtr pObject = pRegion->GetObjectManager()[uIndex];
	if (pObject)
		return pObject->GetID();
	else
		return NULL;
}

long CPGLScript::GetObjectsSize( long lRegionID)
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	return static_cast<long>(pRegion->GetObjectManager().GetCount());
}

long CPGLScript::Image(long lRegionID, LPCTSTR szFileName, LPCTSTR szFlags)
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return 0;

	CPGLImagePtr pImage(new CPGLImage);
	if (!pImage)
		return 0;

	if (!pImage->Load( szFileName ))
		return 0;
	
	ParseImageFormat( pImage, szFlags );

	pRegion->AddObject( pImage );
	Update(pRegion, true);

	return pImage->GetID();
}


void CPGLScript::RemoveObject( long lRegionID, size_t uIndex )
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return;

	pRegion->DeleteObject( uIndex );
}

void CPGLScript::RemoveChild( long lRegionID, size_t uIndex )
{
	CPGLRegionStPtr pRegion = GetRegion(lRegionID);
	if (!pRegion)
		return;

	pRegion->DeleteChild( uIndex );
}

